package com.swak.job.manager.jobs;

import java.time.LocalDateTime;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.swak.Constants;
import com.swak.annotation.Context;
import com.swak.annotation.Flux;
import com.swak.annotation.Job;
import com.swak.entity.SuccessNewFail;
import com.swak.job.JobConstants;
import com.swak.job.JobEvent;
import com.swak.job.JobFragment;
import com.swak.job.JobManager;
import com.swak.job.queue.QueueService;
import com.swak.job.storage.StorageService;
import com.swak.registry.URL;
import com.swak.utils.time.DateTimes;

/**
 * 内部任务：事件任务
 * 
 * @author DELL
 */
@Flux
@Job(id = "EventJob", name = "事件任务", cronExpression = "0/10 * * * * *", executeMethod = "execute", retryTimes = 0, order = true, context = Context.Order)
public class EventJob {

	protected Logger logger = LoggerFactory.getLogger(EventJob.class);

	@Autowired
	private StorageService storageService;
	@Autowired
	private QueueService queueService;
	@Autowired
	private JobManager jobManager;

	/**
	 * 执行重试任务;
	 */
	public void execute(JobFragment fragment) {

		if (logger.isDebugEnabled()) {
			logger.debug(" EventJob 开始执行任务 At {}.", DateTimes.getFormatNow(Constants.Second_Format));
		}

		// 查询失败的任务
		LocalDateTime todayDate = DateTimes.now();
		List<JobEvent> tasks = this.storageService.queryDispatchableEvents(todayDate, 1000);

		if (logger.isDebugEnabled()) {
			logger.debug(" EventJob 需要调度的任务数： {} .", tasks.size());
		}

		for (JobEvent task : tasks) {
			try {
				this.dispatchEvent(task);
			} catch (Throwable e) {
				logger.warn("EventJob {} 执行失败", task.getJobName(), e);
			}
		}

		if (logger.isDebugEnabled()) {
			logger.debug(" EventJob 执行结束.");
		}
	}

	private void dispatchEvent(JobEvent task) {
		List<URL> dispatchers = jobManager.queryDispatchers(task.getJobId());
		URL selectUrl = null;
		if (!dispatchers.isEmpty()) {
			selectUrl = dispatchers.stream().filter(url -> url.getParameter(JobConstants.Leader_key, false)).findFirst()
					.orElse(null);
			if (selectUrl == null) {
				selectUrl = dispatchers.stream().findAny().get();
			}
		}

		boolean success = false;
		if (selectUrl != null) {
			String queue = this.queueService.parseDispatchQueue(selectUrl);
			this.queueService.publishQueue(queue, task);
			success = true;
		}
		this.storageService.dispatchEvent(task.setExecutionTime(DateTimes.now())
				.setStatus(success ? SuccessNewFail.Success.getType() : SuccessNewFail.Fail.getType()));
	}
}